home *** CD-ROM | disk | FTP | other *** search
/ Beginning Mac Programming / Beginning Mac Programming.bin / pc / Open Me for REALbasic 3 / REALbasic 3.2 / Goodies / REAL Software / REALbasic Plug-ins SDK / Examples / obsolete / QTplugin / QTEffect.cpp next >
Encoding:
C/C++ Source or Header  |  1998-10-23  |  9.2 KB  |  342 lines

  1. #include "rb_plugin.h"
  2. #include <Movies.h>
  3. #include <ImageCodec.h>
  4. #include <ImageCompression.h>
  5. #include <QuickTimeComponents.h>
  6. #include "QTEffect.h"
  7.  
  8. //const int gNumberOfSteps = 30;
  9. const int kWidth = 320;
  10. const int kHeight = 200;
  11.  
  12. static ImageDescriptionHandle QTEffects_MakeSampleDescription (EffectSequenceData *effect, short theWidth, short theHeight)
  13. {
  14.     ImageDescriptionHandle        mySampleDesc = NULL;
  15.  
  16.     // create a new sample description
  17.     mySampleDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
  18.     if (mySampleDesc == NULL)
  19.         return(NULL);
  20.     
  21.     // fill in the fields of the sample description
  22.     (**mySampleDesc).idSize = sizeof(ImageDescription);
  23.     (**mySampleDesc).cType = effect->theEffectType;
  24.     (**mySampleDesc).vendor = kAppleManufacturer;
  25.     (**mySampleDesc).temporalQuality = codecNormalQuality;
  26.     (**mySampleDesc).spatialQuality = codecNormalQuality;
  27.     (**mySampleDesc).width = theWidth;
  28.     (**mySampleDesc).height = theHeight;
  29.     (**mySampleDesc).hRes = 72L << 16;
  30.     (**mySampleDesc).vRes = 72L << 16;
  31.     (**mySampleDesc).frameCount = 1;
  32.     (**mySampleDesc).depth = 0;
  33.     (**mySampleDesc).clutID = -1;
  34.     
  35.     return(mySampleDesc);
  36. }
  37.  
  38. static QTAtomContainer QTEffects_CreateTwoSourceEffectDescription (EffectData *effect, OSType theSourceName1, OSType theSourceName2)
  39. {
  40.     QTAtomContainer        myEffectDesc = NULL;
  41.     OSType                myType;
  42.     OSErr                myErr = noErr;
  43.  
  44.     // create a new, empty effect description
  45.     myErr = QTNewAtomContainer(&myEffectDesc);
  46.     if (myErr != noErr)
  47.         goto bail;
  48.  
  49.     // create the effect ID atom: the atom type is kParameterWhatName, and the atom ID is kParameterWhatID
  50.     myType = EndianU32_NtoB(effect->theEffectType);
  51.     myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kParameterWhatName, kParameterWhatID, 0, sizeof(myType), &myType, NULL);
  52.     if (myErr != noErr)
  53.         goto bail;
  54.         
  55.     // add the first source
  56.     myType = EndianU32_NtoB(theSourceName1);
  57.     myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kEffectSourceName, 1, 0, sizeof(myType), &myType, NULL);
  58.     if (myErr != noErr)
  59.         goto bail;
  60.                             
  61.     // add the second source
  62.     myType = EndianU32_NtoB(theSourceName2);
  63.     myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kEffectSourceName, 2, 0, sizeof(myType), &myType, NULL);
  64.  
  65. bail:
  66.     return(myEffectDesc);
  67. }
  68.  
  69. static OSErr QTEffects_SetUpEffectSequence (EffectSequenceData *effect, CGrafPtr port, GDHandle portDevice)
  70. {
  71.     OSErr                        myErr = noErr;
  72.     ImageSequenceDataSource        mySrc1 = 0;
  73.     ImageSequenceDataSource        mySrc2 = 0;
  74.     ImageSequenceDataSource        mySrc3 = 0;
  75.     PixMapHandle                mySrcPixMap;
  76.     PixMapHandle                myDstPixMap;
  77.  /*
  78.     // if an effect sequence is already set up, end it
  79.     if (gCurrentState.fEffectSequenceID != 0L) {
  80.         CDSequenceEnd(gCurrentState.fEffectSequenceID);
  81.         gCurrentState.fEffectSequenceID = 0L;
  82.     }
  83.     
  84.     // if there is a timebase already set up, dispose of it
  85.     if (gCurrentState.fTimeBase != NULL) {
  86.         DisposeTimeBase(gCurrentState.fTimeBase);
  87.         gCurrentState.fTimeBase = NULL;
  88.     }
  89. */    
  90.     // make an effects sequence
  91.     HLock((Handle)effect->fEffectDescription);
  92.  
  93.     // prepare the decompression sequence for playback
  94.     myErr = DecompressSequenceBeginS(
  95.                             &effect->fEffectSequenceID,
  96.                             effect->fSampleDescription,
  97.                             StripAddress(*effect->fEffectDescription),
  98.                             GetHandleSize(effect->fEffectDescription),
  99.                             port,
  100.                             portDevice,
  101.                             NULL,
  102.                             NULL,
  103.                             ditherCopy,
  104.                             NULL,
  105.                             0,
  106.                             codecNormalQuality,
  107.                             NULL);
  108.  
  109.     HUnlock((Handle)effect->fEffectDescription);
  110.     if (myErr != noErr)
  111.         goto bail;
  112.  
  113.     // get the pixel maps for the GWorlds
  114.     mySrcPixMap = GetGWorldPixMap(effect->fGW1);
  115.     myDstPixMap = GetGWorldPixMap(effect->fGW2);
  116.     if ((mySrcPixMap == NULL) || (myDstPixMap == NULL))
  117.         goto bail;
  118.  
  119.     // make the first effect source
  120.     if (effect->fGW1 == NULL)
  121.         goto bail;
  122.     myErr = MakeImageDescriptionForPixMap(mySrcPixMap, &effect->fGW1Desc);
  123.     if (myErr != noErr)
  124.         goto bail;
  125.  
  126.     myErr = CDSequenceNewDataSource(effect->fEffectSequenceID, &mySrc1, FOUR_CHAR_CODE('srcA'), 1, (Handle)effect->fGW1Desc, NULL, 0);
  127.     if (myErr != noErr)
  128.         goto bail;
  129.  
  130.     CDSequenceSetSourceData(mySrc1, GetPixBaseAddr(mySrcPixMap), (**effect->fGW1Desc).dataSize);
  131.  
  132.     // make the second effect source
  133.     if (effect->fGW2 == NULL)
  134.         goto bail;
  135.     myErr = MakeImageDescriptionForPixMap(myDstPixMap, &effect->fGW2Desc);
  136.     if (myErr != noErr)
  137.         goto bail;
  138.  
  139.     myErr = CDSequenceNewDataSource(effect->fEffectSequenceID, &mySrc2, FOUR_CHAR_CODE('srcB'), 1, (Handle)effect->fGW2Desc, NULL, 0);
  140.     if (myErr != noErr)
  141.         goto bail;
  142.  
  143.     CDSequenceSetSourceData(mySrc2, GetPixBaseAddr(myDstPixMap), (**effect->fGW2Desc).dataSize);
  144.  
  145.     // create a new time base and associate it with the decompression sequence
  146.     effect->fTimeBase = NewTimeBase();
  147.     myErr = GetMoviesError();
  148.     if (myErr != noErr)
  149.         goto bail;
  150.  
  151.     SetTimeBaseRate(effect->fTimeBase, 0);
  152.     myErr = CDSequenceSetTimeBase(effect->fEffectSequenceID, effect->fTimeBase);
  153.  
  154. bail:
  155.     return(myErr);
  156. }
  157.  
  158. static OSErr QTEffects_RunEffect (EffectSequenceData *effect, TimeValue theTime)
  159. {
  160.     OSErr                        myErr = noErr;
  161.     ICMFrameTimeRecord            myFrameTime;
  162.  
  163.     // assertions
  164.     if ((effect->fEffectDescription == NULL) || (effect->fEffectSequenceID == 0L))
  165.         goto bail;
  166.  
  167.     // set the timebase time to the step of the sequence to be rendered
  168.     SetTimeBaseValue(effect->fTimeBase, theTime, effect->frames);
  169.  
  170.     myFrameTime.value.hi                = 0;
  171.     myFrameTime.value.lo                = theTime;
  172.     myFrameTime.scale                    = effect->frames;
  173.     myFrameTime.base                    = 0;
  174.     myFrameTime.duration                = effect->frames;
  175.     myFrameTime.rate                    = 0;
  176.     myFrameTime.recordSize                = sizeof(myFrameTime);
  177.     myFrameTime.frameNumber                = 1;
  178.     myFrameTime.flags                    = icmFrameTimeHasVirtualStartTimeAndDuration;
  179.     myFrameTime.virtualStartTime.lo        = 0;
  180.     myFrameTime.virtualStartTime.hi        = 0;
  181.     myFrameTime.virtualDuration            = effect->frames;
  182.     
  183.     HLock((Handle)effect->fEffectDescription);
  184.  
  185.     myErr = DecompressSequenceFrameWhen(
  186.                                         effect->fEffectSequenceID,
  187.                                         StripAddress(*((Handle)effect->fEffectDescription)),
  188.                                         GetHandleSize((Handle)effect->fEffectDescription),
  189.                                         0,
  190.                                         0,
  191.                                         NULL,
  192.                                         &myFrameTime);
  193.                                         
  194.     HUnlock((Handle)effect->fEffectDescription);
  195.     
  196.     if (myErr != noErr)
  197.         goto bail;
  198.     
  199. bail:
  200.     return(myErr);
  201. }
  202.  
  203. void BuildSMPTEEffect(EffectData *data, int id)
  204. {
  205.     long myLong;
  206.     OSType type;
  207.  
  208.     if (id >= 1 && id <= 100)
  209.         type = 'smpt';
  210.     else if (id >= 101 && id <= 200)
  211.         type = 'smp2';
  212.     else if (id >= 201 && id <= 300)
  213.         type = 'smp3';
  214.     else if (id >= 301)
  215.         type = 'smp4';
  216.  
  217.     data->theEffectType = type;
  218.     data->fEffectDescription = QTEffects_CreateTwoSourceEffectDescription(data, FOUR_CHAR_CODE('srcA'), FOUR_CHAR_CODE('srcB'));
  219.     myLong = id;
  220.     QTInsertChild(data->fEffectDescription,
  221.         kParentAtomIsContainer,
  222.         FOUR_CHAR_CODE('wpID'),
  223.         1,
  224.         0,
  225.         sizeof(myLong),
  226.         &myLong,
  227.         NULL);
  228. }
  229.  
  230. void BuildCrossFadeEffect(EffectData *data)
  231. {
  232.     data->theEffectType = 'dslv';
  233.     data->fEffectDescription = QTEffects_CreateTwoSourceEffectDescription(data, FOUR_CHAR_CODE('srcA'), FOUR_CHAR_CODE('srcB'));
  234. }
  235.  
  236. /*
  237. void DoItAll(EffectData *data)
  238. {
  239.     EffectObject obj;
  240.  
  241.     obj.fEffectSequenceID = 0;
  242.     
  243.     obj.fSampleDescription = QTEffects_MakeSampleDescription(&obj, kWidth, kHeight);;
  244.     QTEffects_SetUpEffectSequence(&obj, nil, nil);
  245.     QTEffects_RunEffect(&obj, 5);
  246. }
  247. */
  248.  
  249. static GWorldPtr REALPictToGWorldPtr(REALpicture pic, const Rect &rBounds)
  250. {
  251.     GWorldPtr gw;
  252.     CGrafPtr oldPort;
  253.     GDHandle oldDevice;
  254.  
  255.     GetGWorld(&oldPort, &oldDevice);
  256.  
  257.     NewGWorld(&gw, 16, &rBounds, nil, nil, 0);
  258.     LockPixels(GetGWorldPixMap(gw));
  259.  
  260.     SetGWorld(gw, nil);
  261.     EraseRect(&rBounds);
  262.     REALDrawPicturePrimitive(pic, &rBounds, false);
  263.  
  264.     SetGWorld(oldPort, oldDevice);
  265.  
  266.     return gw;
  267. }
  268.  
  269. void BuildEffectSquence(EffectSequenceData *data, EffectData *effect, REALpicture pic1, REALpicture pic2, int frames)
  270. {
  271.     REALpictureDescription description;
  272.     int w, h;
  273.     Rect r;
  274.  
  275.     data->lastFrame = -1;
  276.     data->currentFrame = 0;
  277.     data->fTimeBase = nil;
  278.  
  279.     REALLockPictureDescription(pic1, &description);
  280.  
  281.     w = description.width;
  282.     h = description.height;
  283.  
  284.     SetRect(&r, 0, 0, w, h);
  285.  
  286.     if (description.pictureType == pictureMacintoshGWorld)
  287.     {
  288.         data->pic1 = pic1;
  289.         REALLockObject((REALobject) pic1);
  290.         data->fGW1 = (GWorldPtr) description.pictureData;
  291.     }
  292.     else
  293.     {
  294.         data->pic1 = nil;
  295.         data->fGW1 = REALPictToGWorldPtr(pic1, r);
  296.     }
  297.  
  298.     REALLockPictureDescription(pic2, &description);
  299.  
  300.     if (description.pictureType == pictureMacintoshGWorld)
  301.     {
  302.         data->pic2 = pic2;
  303.         REALLockObject((REALobject) pic2);
  304.         data->fGW2 = (GWorldPtr) description.pictureData;
  305.     }
  306.     else
  307.     {
  308.         data->pic2 = nil;
  309.         data->fGW2 = REALPictToGWorldPtr(pic2, r);
  310.     }
  311.  
  312.     // copy effect to effectSequence
  313.     data->theEffectType = effect->theEffectType;
  314.     QTCopyAtom(effect->fEffectDescription, kParentAtomIsContainer, &data->fEffectDescription);
  315.  
  316.     data->frames = frames;
  317.  
  318.     data->fSampleDescription = QTEffects_MakeSampleDescription(data, w, h);
  319.  
  320.     NewGWorld(&data->fDest, 16, &r, nil, nil, 0);
  321.     data->destPicture = REALBuildPictureFromGWorld(data->fDest, true);
  322.  
  323.     QTEffects_SetUpEffectSequence(data, data->fDest, GetGWorldDevice(data->fDest));
  324. }
  325.  
  326. void BuildEffectSequenceFrame(EffectSequenceData *data, int frame)
  327. {
  328.     Boolean bNeedsLock;
  329.  
  330.     if (GetPixelsState(GetGWorldPixMap(data->fDest)) & pixelsLocked)
  331.         bNeedsLock = false;
  332.     else
  333.         bNeedsLock = true;
  334.  
  335.     if (bNeedsLock)
  336.         LockPixels(GetGWorldPixMap(data->fDest));
  337.     QTEffects_RunEffect(data, frame);
  338.     REALPictureClearCache(data->destPicture);
  339.     if (bNeedsLock)
  340.         UnlockPixels(GetGWorldPixMap(data->fDest));
  341. }
  342.